﻿/// @file kdbglog.c
#include "stdafx.h"
#include "sbcs.h"
#include "sbctn.h"

//////////////////////////////////////////////////////////////////////////
// 로그 추적기

/// 로그 데이터.
typedef struct kLogData
{
	kDateTime			dt;
	char				cn[32];
	char				fn[32];
} kLogData;

K_LIST_DECL(kLogList, kLogData);

//
static struct kImplDbgLog
{
	kcham				enable;

	kcham				reg;
	kcham				date;

	kLock				lock;
	kLogList			lst;

} k_impl_dbglog =
{
	FALSE,

	FALSE,
	FALSE,

	KLOCK_INIT,
	{NULL, },
};

// 내부 끝
static void _k_lqs_disp(kpointer ptr)
{
	k_slqs(FALSE);
}

/// 디버그 로그 켬/끔.
/// @date 2013-12-22
/// @param run 참이면 켜고, 거짓이면 끔.
void k_slqs(kcham run)
{
	if (run)
	{
		k_return_if_ok(k_impl_dbglog.enable);

		k_impl_dbglog.enable = TRUE;

		k_list_init(kLogList, &k_impl_dbglog.lst);

		if (!k_impl_dbglog.reg)
		{
			k_impl_dbglog.reg = TRUE;
			k_atexit_p(_k_lqs_disp, NULL);
		}
	}
	else
	{
		k_return_if_fail(k_impl_dbglog.enable);

		k_impl_dbglog.enable = FALSE;

		k_list_disp(kLogList, &k_impl_dbglog.lst);
	}
}

/// 디버그 로그 넣기.
/// @date 2013-12-22
/// @param clscn 클래스.
/// @param fn  함수.
void k_lqs(const char* cn, const char* fn)
{
	kLogData d;

	k_return_if_fail(k_impl_dbglog.enable);
	k_return_if_fail(fn);

	k_now(&d.dt);
	if (cn)
		k_strncpy(d.cn, cn, sizeof(d.cn));
	else
		d.cn[0] = '\0';
	k_strncpy(d.fn, fn, sizeof(d.fn));

	K_LOCK(k_impl_dbglog.lock);
	k_list_append(kLogList, &k_impl_dbglog.lst, d);
	K_UNLOCK(k_impl_dbglog.lock);
}

// 디버그 로그 파일로 뽑는 콜백
static void _k_dump_lqs_callback(kFile* file, const kLogData* d)
{
	if (k_impl_dbglog.date)
	{
		if (d->cn[0])
		{
			k_file_printf(file, "[%04d-%02d-%02d %02d:%02d:%02d.%03d] %s.%s",
				d->dt.year, d->dt.month, d->dt.date, d->dt.hour, d->dt.minute, d->dt.second,
				d->dt.millisecond, d->cn, d->fn);
		}
		else
		{
			k_file_printf(file, "[%04d-%02d-%02d %02d:%02d:%02d.%03d] %s",
				d->dt.year, d->dt.month, d->dt.date, d->dt.hour, d->dt.minute, d->dt.second,
				d->dt.millisecond, d->fn);
		}
	}
	else
	{
		if (d->cn[0])
		{
			k_file_printf(file, "[%02d:%02d:%02d.%03d] %s.%s",
				d->dt.hour, d->dt.minute, d->dt.second,
				d->dt.millisecond, d->cn, d->fn);
		}
		else
		{
			k_file_printf(file, "[%02d:%02d:%02d.%03d] %s",
				d->dt.hour, d->dt.minute, d->dt.second,
				d->dt.millisecond, d->fn);
		}
	}
}

/// 디버그 로그 파일로 뽑기.
/// @date 2013-12-22
/// @param filename 파일 이름.
/// @param date	    날짜 출력 여부.
/// @param clear    출력 후 보관 로그 삭제 여부.
void k_dumplqs(const char* filename, kcham date, kcham clear)
{
	kFile* file;
	kDateTime dt;

	k_return_if_fail(filename);

	file = k_file_new(filename, "a");
	k_return_if_fail(file);

	k_now(&dt);
	k_file_seek(file, 0, KSEEK_END);
	k_file_printf(file, "\n\n* dump [%04d-%02d-%02d %02d:%02d:%02d.%03d]",
		dt.year, dt.month, dt.date, dt.hour, dt.minute, dt.second, dt.millisecond);

	K_LOCK(k_impl_dbglog.lock);

	k_impl_dbglog.date = date;

	k_list_ref_foreach(kLogList, &k_impl_dbglog.lst, _k_dump_lqs_callback, file);

	if (clear)
		k_list_clear(kLogList, &k_impl_dbglog.lst);

	K_UNLOCK(k_impl_dbglog.lock);
}
